package com.zero.manage.web.components.base;


import cn.hutool.core.util.IdUtil;
import com.querydsl.jpa.impl.JPAQueryFactory;
import io.gitee.zerowsh.config.Utils;
import io.gitee.zerowsh.enums.ResultEnums;
import io.gitee.zerowsh.util.PageResult;
import io.gitee.zerowsh.util.PublicResult;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

/**
 * 业务基类
 *
 * @author zero
 */
@SuppressWarnings("ALL")
@NoArgsConstructor
public abstract class BaseService<E extends BaseEntity<ID>, ID, M extends BaseDao<E, ID>, Q extends BaseQuery> implements IBase<E, ID, Q> {
    @Autowired
    protected M mapper;
    @Autowired
    protected JPAQueryFactory jpa;

    @Override
    public PublicResult add(E e) {
        long currentTime = Utils.getCurrentTime();
        /**
         * 新增时，主键、创建时间、修改时间进行替换，防止前端传值，产生错误数据
         */
        Utils.setFieldValueByFieldName(e, "id", IdUtil.randomUUID());
        Utils.setFieldValueByFieldName(e, "createTime", currentTime);
        Utils.setFieldValueByFieldName(e, "updateTime", currentTime);
        mapper.save(e);
        return PublicResult.addOk();
    }

    @Override
    public PublicResult add(E e, Map<String, Object> maps) {
        if (!CollectionUtils.isEmpty(maps)) {
            for (Map.Entry<String, Object> map : maps.entrySet()) {
                Utils.setFieldValueByFieldName(e, map.getKey(), map.getValue());
            }
        }
        this.add(e);
        return PublicResult.addOk();
    }

    @Override
    public PublicResult update(E e) {
        Optional<E> byId = mapper.findById(e.getKeyId());
        if (!byId.isPresent()) {
            return PublicResult.updateOk();
        }
        /**
         * 创建时间处理
         *  1.获取以前的值
         *  2.进行替换，防止调用接口修改
         */
        Object createTime = Utils.getFieldValueByFieldName("createTime", byId.get());
        Utils.setFieldValueByFieldName(e, "createTime", createTime);
        /**
         * 修改时间处理
         */
        Utils.setFieldValueByFieldName(e, "updateTime", Utils.getCurrentTime());
        mapper.save(e);
        return PublicResult.updateOk();
    }

    @Override
    public PublicResult update(E e, List<String> keys) {
        Optional<E> byId = mapper.findById(e.getKeyId());
        if (!byId.isPresent()) {
            return PublicResult.updateOk();
        }
        /**
         * 创建时间处理
         *  1.获取以前的值
         *  2.进行替换，防止调用接口修改
         */
        Object createTime = Utils.getFieldValueByFieldName("createTime", byId.get());
        Utils.setFieldValueByFieldName(e, "createTime", createTime);
        if (!CollectionUtils.isEmpty(keys)) {
            for (String key : keys) {
                //获取以前的值
                Object obj = Utils.getFieldValueByFieldName(key, byId.get());
                //进行替换，防止调用接口修改
                Utils.setFieldValueByFieldName(e, key, obj);
            }
        }
        /**
         * 修改时间处理
         */
        Utils.setFieldValueByFieldName(e, "updateTime", Utils.getCurrentTime());
        mapper.save(e);
        return PublicResult.updateOk();
    }

    @Override
    public PublicResult<Optional<E>> get(ID id) {
        return PublicResult.queryOk(mapper.findById(id));
    }


    @Override
    public PublicResult<List<E>> getByIds(Iterable<ID> ids) {
        return PublicResult.queryOk(mapper.findAllById(ids));
    }

    @Override
    public PublicResult<List<E>> list(Q q) {
        return PublicResult.queryOk(StreamSupport.stream(mapper.findAll(q.predicate(), q.getSort()).spliterator(), false).collect(Collectors.toList()));
    }

    @Override
    public PageResult<List<E>> pageList(Q q) {
        Page<E> all = mapper.findAll(q.predicate(), q.getPageable());
        return PageResult.<List<E>>builder()
                .code(ResultEnums.QUERY_OK.getKey())
                .msg(ResultEnums.QUERY_OK.getMsg())
                .page(q.getPage())
                .pageSize(q.getPageSize())
                .total(all.getTotalElements())
                .data(all.getContent())
                .build();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PublicResult deleteByIds(List<E> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return PublicResult.delFail("参数不能为空");
        }
        mapper.deleteInBatch(ids);
        return PublicResult.delOk();
    }
}